<script  setup>
import { ref, reactive, computed, h, onMounted, nextTick } from "vue";
import axios from 'axios';
import io from "socket.io-client";
import $ from "jquery";
import showdown from "showdown";
import showdownHighlight from "showdown-highlight";
import {ElProgress, ElDialog } from 'element-plus';

import EmojiPicker from "vue3-emoji-picker"; // emoji .npm install vue3-emoji-picker
import "vue3-emoji-picker/css"; //emoji

import { _dateTimeFormatter } from "../utils/dateutil.js";

// import domtoimage from 'dom-to-image'; // 截图
import kscreenshot from 'kscreenshot' // 鼠标选中截图

import realtimeBoard from "./realtimeBoard.vue";

const baseBackEndServerUrl = "http://localhost:3000";
const baseFrontEndServerUrl = "http://localhost:5173";
var markdown = ref("");
showdown.setFlavor("github"); // 设置风格 。 没区别！
var convertedMarkdown = computed(() => {
  const converter = new showdown.Converter({
    extensions: [
      showdownHighlight({
        // Whether to add the classes to the <pre> tag, default is false
        pre: true,
        // Whether to use hljs' auto language detection, default is true
        auto_detection: true,
      }),
    ],
  });
  return converter.makeHtml(markdown.value);
});

var toggoleEmoji = ref(false);
//表情
function onSelectEmoji(emoji) {
  console.log("emoji===>", emoji);
  // markdown.value += emoji.i;

  const textarea = inputbox.value;
  const startPos = textarea.selectionStart;
  const endPos = textarea.selectionEnd;
  const value = textarea.value;

  const newValue =
    value.substring(0, startPos) + emoji.i + value.substring(endPos);

  markdown.value = newValue;
  textarea.selectionStart = textarea.selectionEnd = startPos + emoji.length;
  textarea.focus();

  toggleEmojiFunction();
}
const toggleEmojiFunction = function () {
  toggoleEmoji.value = !toggoleEmoji.value;
};
/**
 * 所有的消息列表，格式：
 * { type: system || talk ,content:"xxxx" , time: "2023-01-01 15:23" , from: "username" , to:"username"} // 群发的时候to=all
 *
 */
var messageList = reactive([]);
// 做一个测试数据
// messageList = [
//     {type: "system" ,content:"123加入了群聊" , time: "2023-01-01 15:23" , from: "123" ,fromavatar:"http://localhost:5173/assets/images/avatar01.jpg", to:"all"},
//     {type: "talk" ,content:"你好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar02.jpg", to:"all"},
//     {type: "talk" ,content:"你也好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar03.jpg", to:"all"},
//     {type: "system" ,content:"456离开了了群聊" , time: "2023-01-01 16:13" , from: "456",fromavatar:"http://localhost:5173/assets/images/avatar04.jpg" , to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},
//     {type: "talk" ,content:"大家好才是真的好" , time: "2023-01-01 15:23" , from: "srx" ,fromavatar:"http://localhost:5173/assets/images/avatar05.jpg", to:"all"},

// ];

function creatMsg(type, contentType, content, from, avata, to) {
  var obj = {
    type: type,
    contentType: contentType,
    content: content,
    time: _dateTimeFormatter(new Date()),
    from: from,
    fromavatar: avata,
    to: to,
  };
  messageList.push(obj);

  return obj;
}
function createSystemMsg(content, from, avata) {
  return creatMsg("system", "text", content, from, avata, "all");
}
function createTalkMsg(content, from, avata, to) {
  return creatMsg("talk", "text", content, from, avata, to);
}
function createImageMsg(content, from, avata, to) {
  return creatMsg("talk", "image", content, from, avata, "all");
}


var socket = io(baseBackEndServerUrl);

/**
 * 前端连接服务器
 */
socket.on("connect", () => {
  console.log("Connected to server");
});

/**
 * 前端动画
 */
// imgs class 10个图
var userAvata = ref(baseFrontEndServerUrl + "/assets/images/avatar01.jpg");
var sessionUserAvata = sessionStorage.getItem("userAvata");
if (
  sessionUserAvata != null &&
  sessionUserAvata != "null" &&
  sessionUserAvata != ""
) {
  userAvata.value = sessionUserAvata;
}

const setImgPickedUp = function (e) {
  console.log(e.target);
  var dom = e.target;

  $(".avatar li").removeClass(); // jquery 设置样式还是很方便。
  dom.parentNode.className = "now";
  userAvata.value = dom.src; // H5
  console.log(userAvata.value);
};

var showLogin = ref(true);

/**
 * 从本地存储里取username
 */
var sessionUsername = sessionStorage.getItem("username");
console.log("sessionUsername=" + sessionUsername);
var username = ref(sessionUsername);
// debugger
if (
  sessionUsername == null ||
  sessionUsername == "" ||
  sessionUsername == "null" ||
  sessionUsername == undefined
) {
  console.log("set showlogin = true");
  showLogin.value = true;
} else {
  console.log("set showlogin = false");
  showLogin.value = false;
}

console.log("showLogin.value =" + showLogin.value);

/**
 * 从本地存储里取userList.
 */
var userList = ref([]);
// var sessionUserList = sessionStorage.getItem('userList')
var sessionUserList = JSON.parse(sessionStorage.getItem("userList"));
console.log("sessionUserList=", sessionUserList);
if (sessionUserList != null && sessionUserList.length > 0) {
  sessionUserList.forEach((user) => {
    console.log(user.username, user.avata);
  });
  userList.value = sessionUserList;
}

// 显示聊天室人数
var userCount = computed(() => {
  if (userList.value == null) {
    return 0;
  } else {
    return userList.value.length;
  }
});

/**
 * 前端发送login请求
 */
const loginHandler = function () {
  if (username.value == null) {
    alert("error: username is required!");
    return;
  }
  console.log(username.value, userAvata.value);
  socket.emit("login", { username: username.value, avata: userAvata.value });
};
var message = ref("");

/**
 * 前端处理login成功
 */
socket.on("loginSuccess", (_userList) => {
  // {username,avata}
  console.log("loginSuccess __userList=", _userList);
  showLogin.value = false; // 就不用显示login画面了。但是一刷新就重置了。怎么办？
  userList.value = _userList;
  console.log(
    "loginSuccess 客户端接收到最新的用户列表：userList.value=",
    userList.value
  );

  sessionStorage.setItem("username", username.value);
  sessionStorage.setItem("userAvata", userAvata.value);
  sessionStorage.setItem("userList", JSON.stringify(userList.value));

  // 消息列表
  createSystemMsg(
    username.value + "加入了群聊",
    username.value,
    userAvata.value
  );
});

/**
 * 显示哪个用户已经登陆。
 */
var newUser = ref(null);
socket.on("userListChanged", ({ userList: _userList, newUser: _newUser }) => {
  userList.value = _userList;
  console.log(
    "userListChanged 客户端接收到最新的用户列表：userList.value=",
    userList.value,
    "newUser:",
    _newUser
  );
  sessionStorage.setItem("userList", JSON.stringify(userList.value));
  newUser.value = _newUser.username; // 欢迎新用户
  // 消息列表
  createSystemMsg(
    username.value + "加入了群聊",
    username.value,
    userAvata.value
  );
});

/**
 * 前端处理重复登录
 */
var serverUserList = [];
var serverUserName = "";
socket.on("noneed2login", (data) => {
  // console.log("noneed2login",serverUserList,userObj);
  console.log("no need to login. data===>", data);
  message.value = "已经登陆过了。";
  userList.value = data.userList;
  username.value = data.user.username;
  userAvata.value = data.user.avata;
  sessionStorage.setItem("username", username.value);
  sessionStorage.setItem("userAvata", userAvata.value);
  sessionStorage.setItem("userList", JSON.stringify(userList.value));

  showLogin.value = false;
});

/**
 * 前端关闭浏览器时，清除session
 */
socket.on("disconnect", () => {
  // 删除存储在sessionStorage中的数据
  sessionStorage.removeItem("username");
  sessionStorage.removeItem("userList");

  // 清空sessionStorage中的所有数据
  //sessionStorage.clear();
  console.log("Disconnected from server");
});

/**
 * 有人退出，处理服务器群发推送的消息。
 */
socket.on("someoneDisconnect", (_userList) => {
  userList.value = _userList;
  console.log(
    "someoneDisconnect 客户端接收到最新的用户列表：userList.value=",
    userList.value
  );

  sessionStorage.setItem("username", username.value);
  sessionStorage.setItem("userAvata", userAvata.value);
  sessionStorage.setItem("userList", JSON.stringify(userList.value));

  // 消息列表
  createSystemMsg(
    username.value + "退出了群聊",
    username.value,
    userAvata.value
  );
});

/**
 * 发普通文本
 */
var textarea = ref("");
const sendMsg = function () {
  if (markdown.value == "" || markdown.value == "") {
    return;
  }
  var obj = {
    type: "talk",
    contentType: "text",
    content: markdown.value,
    from: username.value,
    fromavata: userAvata.value,
    to: "all",
    time: _dateTimeFormatter(new Date()),
  }; // 暂定群聊
  socket.emit("sendMsgToServer", obj);
  markdown.value = "";
};

/**
 * receive others text message
 */
// 接广播消息。
socket.on("broadcaseMsgToClients", (obj) => {
  var converter = new showdown.Converter(),
    html = converter.makeHtml(obj.content);
  createTalkMsg(html, obj.from, obj.fromavata);
  console.log("messageList==>", messageList);

  nextTick(() => {
    var msgBoxes = document.getElementsByClassName("box-bd");

    var target = msgBoxes[msgBoxes.length - 1];
    target.scrollTop = target.scrollHeight;
  });
});

/**
 * 发小图OK。大图自动断连接（NG）
 *
 */

const sendImg = function (e) {
  const selectedFile = e.target.files[0];
  var fr = new FileReader();

  fr.onloadend = function (ev) {
    console.log("sendImage ev.target.result", ev.target.result);
    //fr.result在控制台输出Base64编码的字符串
    var obj = {
      type: "image",
      content: fr.result,
      from: username.value,
      fromavata: userAvata.value,
      to: "all",
    }; // 暂定群聊
    socket.emit("sendImage", obj);
  };

  if (selectedFile && selectedFile.type.match("image.*")) {
    fr.readAsDataURL(selectedFile);
  } else {
    console.log("error：selectedFile 类型不对！！");
  }
};


const upload = () => {
  // 触发文件选择框
  const fileInput = document.querySelector("input[type=file]");
  fileInput.click();
};

const handleFileChange = (event) => {
  // 处理文件选择事件
  sendImg(event);
  //   const files = event.target.files;
};

/**
 * receive others image message
 */
socket.on("broadcaseImageToClients", (obj) => {
  // {
  //         usernama:username.value,
  //         avata: userAvata.value,
  //         img : fr.result
  //     })
  console.log("broadcaseImageToClients ", obj);
  createImageMsg(obj.content, obj.from, obj.fromavata, obj.to);
});

//从服务器上获得大图
const getBigImage = function () {
  socket.emit("getBigImage");
};

var imgChunks = [];
socket.on("img-chunk", (chunk) => {
  var srx = document.getElementById("srx");
  imgChunks.push(chunk);
  srx.setAttribute("src", "data:image/jpeg;base64," + window.btoa(imgChunks));
});

var inputbox = ref("");
/**
 * Enter 发送数据
 *
 */
function handleEnterPress(event) {
  if (!event.shiftKey) {
    event.preventDefault();

    // if(fileBolb !=null){
    //   console.log(fileBolb.name+","+fileBolb.size);
    //   uploadFile();
    //   fileBolb = {};
    // }

    sendMsg();
  }
}

/**
 * shift + enter 换行
 */
const insertNewLine = () => {
  //        console.log("markdown.value=",markdown.value,"markdown.selectionStart=",inputbox.value.selectionStart);

  markdown.value =
    markdown.value.substring(0, inputbox.value.selectionStart) +
    "\n" +
    markdown.value.substring(inputbox.value.selectionStart);
};

const handleScroll = () => {
  const el = inputbox.value;
  if (el.scrollTop !== el.scrollHeight - el.clientHeight) {
    el.scrollTop = el.scrollHeight - el.clientHeight;
  }
};

var markdownPreview = ref(false);
const togglePreview = function () {
  markdownPreview.value = !markdownPreview.value;
};

var showBoard = ref(false);
const toggleShowBoard = function(){
  
  showBoard.value = !showBoard.value;
  console.log("toggleShowBoard! showBoard Event Emit ,showBoard.value="+showBoard.value);
  socket.emit("showBoard",showBoard.value)
}


socket.on("onShowBoardData",(isOtherShowBoard)=>{
  console.log("onShowBoardData param:isOtherShowBoard="+isOtherShowBoard);
  if(isOtherShowBoard){
    showBoard.value = true;
  }else{
    showBoard.value = false;
  }
})

/**
 * 截图用
 */
 function mouseCutImg(){

    new kscreenshot({
      key: 65,
      needDownload: false,
      endCB(e) { //截图成功回调
        console.log(e)
        var obj = {
          type: "talk",
          contentType: "image",
          content: e,
          time: _dateTimeFormatter(new Date()),
          from: username.value,
          fromavata: userAvata.value,
          to: "all",
        };
        socket.emit("sendImage",obj);
      },
      cancelCB(e) { //截图失败回调
        console.log(e)
      }
    }).startScreenShot()

}


/**
 * 截取聊天记录--> clipboard
 */
function captureScreenshot() {
    
    var node = document.getElementById('chatBox');
  
    domtoimage.toPng(node)
        .then(function (dataUrl) {
            var img = new Image();
            img.src = dataUrl;
            document.body.appendChild(img);
        })
        .catch(function (error) {
            console.error('oops, something went wrong!', error);
        });
  }

/**
 * 把剪贴板的图片拷贝到聊天对话中。
 * 
 */
function textPast(e){
        console.log(e)
        e.preventDefault();
        var text;
        var clp = (e.originalEvent || e).clipboardData;
        var type=clp.items[0].type;
        console.log(type)  // 可通过类型来进行粘贴文件的判断  【重点】
        //兼容针对于opera ie等浏览器
        if (clp === undefined || clp === null) {
            text = window.clipboardData.getData("text") || "";
            if (text !== "") {
                if (window.getSelection) {
                // 针对于ie11 10 9 safari
                    var newNode = document.createElement("span");
                    newNode.innerHTML = text; 
                  window.getSelection().getRangeAt(0).insertNode(newNode);
                } else {
                // 兼容ie10 9 8 7 6 5
                    document.selection.createRange().pasteHTML(text);
                }
            }
        } else {
        // insertHTML ,insertText 以及其他的事件，具体可参考相关文档
          if(type.match(/image/)){
            var blob = clp.items[0].getAsFile();
            uploadFile(blob);
                // var file = new FileReader();
                // // file.onload=function(){
                // //   console.log(file.result)
                // //   var obj = {
                // //     type: "talk",
                // //     contentType: "image",
                // //     content: file.result,
                // //     time: _dateTimeFormatter(new Date()),
                // //     from: username.value,
                // //     fromavata: userAvata.value,
                // //     to: "all",
                // //   };
                // //   console.log("sendImage obj=",obj);
                // //   socket.emit("sendImage", obj);
                // }
                // file.readAsDataURL(blob);
          }else{
            //兼容chorme或hotfire
            text = clp.getData('text/plain') || "";
            if (text !== "") {
                document.execCommand('insertText', false, text);
            }
          }
        }
}

/**
 * 点击图片，弹出新层，显示图片原来大小，然后单击该层，关闭该层。
 * @param {} imgsrc 
 */
function showImagePreview(imgsrc) {
      const image = new Image();
      image.src = imgsrc;
      image.onload = () => {
        // 创建弹出层
        const previewContainer = document.createElement('div');
        previewContainer.style.position = 'fixed';
        previewContainer.style.top = 0;
        previewContainer.style.bottom = 0;
        previewContainer.style.left = 0;
        previewContainer.style.right = 0;
        previewContainer.style.backgroundColor = 'rgba(0,0,0,0.8)';
        previewContainer.style.display = 'flex';
        previewContainer.style.justifyContent = 'center';
        previewContainer.style.alignItems = 'center';
        document.body.appendChild(previewContainer);
        // 在弹出层中添加图片
        const previewImage = document.createElement('img');
        previewImage.src = imgsrc;
        previewImage.style.maxWidth = '200%';
        previewImage.style.maxHeight = '200%';
        previewContainer.appendChild(previewImage);
        // 点击弹出层，关闭预览
        previewContainer.addEventListener('click', () => {
          document.body.removeChild(previewContainer);
        });
      };
}


//////////////////// drag file to upload  test ///////////////////////////
var message  =ref("")
const CHUNK_SIZE = 1024 * 1024; // 1MB chunk size
async function handelDropFile(event) {
    event.preventDefault(); // 阻止浏览器打开文件并显示。
    
    const files = event.dataTransfer.files;
    const file = files[0];
    
    uploadFile(file);
}


const uploadProgress = ref(0)
var dialogVisible = ref(false);
  
async function uploadFile(file){
  let start = 0;
    let end = CHUNK_SIZE;
    dialogVisible.value = true; // 显示上传进度对话框
    uploadProgress.value = 0 ;
    while (start < file.size) {
      if(end>file.size){
        end = file.size;
      }

      const chunk = file.slice(start, end); // start起始位置包括该位置，end终止位置不包括该位置（也就是说该位置的前一个是包括的）
      const formData = new FormData();
      formData.append('file', chunk);
      formData.append('filename', encodeURI(file.name));
      formData.append('username',username.value);
      formData.append('useravata',userAvata.value);
      console.log("start="+start+"~ end="+end+" / "+ file.size);
      console.log("uploadProgress="+uploadProgress.value+"dialogVisible="+dialogVisible.value);
      try{
         

        await axios.post('http://localhost:8080/upload', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
            'Content-Range': `bytes ${start}-${end}/${file.size}`,
          },
          onUploadProgress: (progressEvent) => {
                if (progressEvent.total > 0) {
                  uploadProgress.value = Math.round((start + progressEvent.loaded) * 100 / file.size);
                  console.log("uploadProgress="+uploadProgress.value+" progressEvent.loaded="+ progressEvent.loaded);
                }
          }
        });
      }catch(e){
        console.log("upload error:"+e);
      }finally{
        console.log("upload finally");
        if(uploadProgress.value == 100){
          setTimeout(()=>{
            dialogVisible.value = false; // 关闭上传进度对话框
          },2000)
        }
      }

      start = end;
      end = Math.min(end + CHUNK_SIZE, file.size);
    }// end of while
}


// 获得文件扩展名
function getFileExtension(filename) {
  return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
}

// 服务器存储上传文件完成后，发送给客户端消息，客户端响应服务器的消息
socket.on('fileUploaded', (fileResponseObj) => {
  const {"url":enCodeURL,"from":from,"fromAvata":fromAvata} = fileResponseObj;
   var filePath = decodeURI(enCodeURL);
   console.log("on fileUploaded: filePath="+filePath+",from="+from);

   // 获取文件后缀
   const ext = filePath.split('.').pop();

  // 判断是否为图片类型
  if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext.toLowerCase())) {

    console.log("is image.");
    // 是图片类型，创建 img 元素
    // 显示图片 这段主要为了测试。当然不一定是图片，也可能是其他文件。
    // const img = document.createElement('img');
    // img.src = filePath;
    // img.onclick=()=>{
    //     console.log("img onclick");
    //     showImagePreview(filePath); // 最大为原来的200%
    // }
   
    // img.onload = () => {
    //   // 获取图片的宽度和高度
    //   const width = img.width;
    //   const height = img.height;

    //   // 设置最大宽度和最大高度
    //   const maxWidth = 320;
    //   const maxHeight = 320;

    //   // 计算缩放比例
    //   const ratio = Math.min(maxWidth / width, maxHeight / height);

    //   // 缩放图片
    //   img.width = width * ratio;
    //   img.height = height * ratio;
    // };

  

  createImageMsg(filePath,from,fromAvata,"all");


  } else {

    console.log("not image file");

    // 不是图片类型，创建 a 元素
    const link = document.createElement('a');
    link.href = filePath+"&username="+username.value;
    //link.download = getFileExtension(filePath);
    
    
    const fileName = filePath.substring(filePath.lastIndexOf('=') + 1);
    link.download =fileName; // TODO: 有问题，下载的文件名不对。文件名是汉字的时候下载得不对。


    link.textContent = fileName;

    // 放到输入框textarea中

    inputbox.value.value += link.outerHTML;
    markdown.value +=link.outerHTML;
  }

});

</script>

<template>
  <div class="loginPage">
    
    <!-- 注册部分 -->
    <div class="register-box" style="display: none"></div>

    <!-- 登陆部分 -->
    <div class="login_box" v-if="showLogin" style="display: block">
      <h3>用户登录</h3>
      <p>用户名</p>
      <input
        type="text"
        placeholder="请输入用户名"
        id="username"
        v-model="username"
      />
      <p>选择头像</p>
      <ul class="avatar" id="login_avatar">
        <li class="now">
          <img
            src="/assets/images/avatar01.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar02.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar03.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar04.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar05.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar06.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar07.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar08.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar09.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
        <li>
          <img
            src="/assets/images/avatar10.jpg"
            @click="setImgPickedUp($event)"
            alt=""
          />
        </li>
      </ul>
      <button class="weui-btn" id="loginBtn" @click="loginHandler()">
        登录
      </button>
    </div>

    <!-- 聊天室部分 -->
    <div class="container" v-if="!showLogin">
      <!-- 用户列表 -->
      <div class="user-list">
        <div class="header">
          <div class="avatar">
            <img class="img avatar_url" :src="userAvata" alt="" />
          </div>
          <div class="info">
            <!--  -->
            <h3 class="username">{{ username }}</h3>
          </div>
        </div>
        <div class="title"><h3>用户列表(<span id="userCount">{{ userCount }}</span>)</h3></div>
        <ul>
          <li class="user" v-for="usr in userList">
            <div class="avatar"><img :src="usr.avata" alt="" /></div>
            <div class="name">{{ usr.username }}</div>
          </li>
        </ul>
      </div>
      <!-- 聊天主窗口 -->
      <div class="box">
        
        <!-- 聊天窗口主体区域 -->

        <div ref="chatBox" id="chatBox" class="box-bd">


          <div id="file-list">
         
          </div>
          
        
         
          

          <div v-for="(msg, index) in messageList">
            <div v-if="msg.type == 'system'" class="system">
              <p class="message_system">
                <span class="content">{{ msg.content }}</span>
              </p>
            </div>

           

            <div
              v-else-if="msg.type == 'talk' && msg.from == username"
              class="message-box"
            >
              <div class="my message">
                <img class="avatar" :src="msg.fromavatar" alt="" />
                <div class="content">
                  <div class="bubble">
                    <div v-if="msg.contentType == 'text'" class="bubble_cont">
                      <span v-html="msg.content"></span>
                    </div>
                    <div v-if="msg.contentType == 'image'" class="bubble_cont">
                      <img :src="msg.content" alt="ended pic" @click="showImagePreview(msg.content)" />
                    </div>
                  </div>
                  <div class="system">
                    <p class="message_system">
                      <span class="content">{{ msg.time }}</span>
                    </p>
                  </div>
                </div>
              </div>
            </div>

            <div
              v-else-if="msg.type == 'talk' && msg.from != username"
              class="message-box"
            >
              <div class="other message">
                <img class="avatar" :src="msg.fromavatar" alt="" />
                <div class="content">
                  <div class="nickname">{{ msg.from }}</div>
                  <div class="bubble">
                    <div v-if="msg.contentType == 'text'" class="bubble_cont">
                      <span v-html="msg.content"></span>
                    </div>
                    <div v-if="msg.contentType == 'image'" class="bubble_cont">
                      <img :src="msg.content" alt="ended pic" @click="showImagePreview(msg.content)" />
                    </div>
                  </div>
                </div>

                <div class="system">
                  <p class="message_system">
                    <span class="content">{{ msg.time }}</span>
                  </p>
                </div>
              </div>
            </div>
          </div>
          <!--end of for-->
          <!-- <teleport to="chatBox"> -->
          <div class="popup" v-if="markdownPreview == true">
            <div v-html="convertedMarkdown" class="popup-inner"></div>
          </div>
          <div class="popupBoard" v-if="showBoard == true">
            <!-- <div  class="popup-inner"></div> -->
            <realtimeBoard :socket="socket" :toggleBoard="toggleShowBoard"></realtimeBoard>
          </div>
          <div class="popupProgress" v-if="dialogVisible == true">
            <!-- upload file progress -->
            <h1>文件上传中...</h1>
            <!-- <div class="custom-progress">
              <el-progress class="custom-progress-bar" :percentage="uploadProgress" status="success"></el-progress>
            </div> -->

              <div class="demo-progress">
                <el-progress type="dashboard" :percentage="uploadProgress">
                  <template #default="{ percentage }">
                    <span class="percentage-value">{{ uploadProgress }}%</span>
                    <span class="percentage-label">Progressing</span>
                  </template>
                </el-progress>
              </div>
          </div>
        </div>
        <!--end of chatBox-->

        <div class="popupemoji" v-if="toggoleEmoji == true">
          <div class="popup-inner">
            <EmojiPicker
              :native="true"
              @select="onSelectEmoji"
              v-if="toggoleEmoji"
            />
          </div>
        </div>
        
        <!-- </teleport> -->
        <canvas ref="canvasRef"></canvas>

          <!-- 聊天窗口底部区域 -->
        <div class="box-ft">
          <!-- 工具栏 -->
          
          <div class="toolbar">
            <div class="tool">
            
              <font-awesome-icon :icon="['fa','paint-brush']"
                @click="toggleShowBoard()"
              />
            </div>
            <div class="tool">
              <font-awesome-icon
                :icon="['fass', 'face-smile']"
                @click="toggleEmojiFunction()"
              />
            </div>
            <div class="tool">
              <font-awesome-icon
                :icon="['fa', 'scissors']"
                @click="mouseCutImg()"
              />
            </div>
            <div class="tool">
              <font-awesome-icon
                :icon="['fa', 'folder-open']"
                @click="upload"
              />
            </div>
            <div class="tool">
              <font-awesome-icon icon="fa fa-play" @click="togglePreview()" />
            </div>
            <input
              type="file"
              ref="fileInput"
              style="display: none"
              @change="handleFileChange"
            />
          </div>

          <!-- 内容输入区域 -->
          <div class="content">
            <!-- div添加一个属性：contenteditable 可编辑div文本内容-->
            <textarea
              ref="inputbox"
              v-model="markdown"
              class="text"
              @keydown.enter.prevent="handleEnterPress($event)"
              @keydown.enter.shift.prevent="insertNewLine()"
              @scroll="handleScroll"
              @paste="textPast($event)"
              @drop.prevent="handelDropFile($event)"
              placeholder="shift回车换行，回车发送"
            ></textarea>
          </div>

         
         
        </div>
        <!--end of box-ft-->
      </div>
      <!--end of box-->
    </div>
    <!--end of container-->
  </div>
  <!--end of loginPage-->
  
</template>


<style scoped>
@import url(../assets/css/index.css);
/* .loginPage{
        height: 100%;
        width:100%;
        background: url('../assets/images/bg.jpg') no-repeat center center;
        background-size: cover;
    } */
.tool {
  display: inline-block;
  width: 40px;
  height: 40px;
  /* border: 1px solid red; */
}

/* .container{
        transition:  all 3000ms ease-in;
    } */
/*  不生效
    .v-enter-active,
    .v-leave-active {
    transition: opacity 2s ease;
    }

    .v-enter-from,
    .v-leave-to {
    opacity: 0;
    } */

input[type="file"] {
  position: absolute;
  opacity: 0;
  width: 50%;
  height: 50%;
  top: 0;
  left: 0;
  cursor: pointer;
}
.popup {
  position: fixed;
  top: 100px;
  bottom: 200px;

  min-width: 400px;
  left: 400px;
  right: 200px; 

  /* position: absolute;
  top: 0;
  left: 0;
  bottom: 20px;
  width: 90%;
  height: 90%; */

  z-index: 99;
  background: rgba(0, 0, 0, 0.1);
  display: flex;
}

.popupBoard {
  position: fixed;
  top: 0px;
  bottom: 0px;

  min-width: 400px;
  left: 0px;
  right: 10px; 

  z-index: 99;
  background: #fff;
  /* rgba(0, 0, 0, 0.1); */
  /* background: red; */
  display: flex;
}
.popupProgress {
  position: fixed;
  top: 0px;
  bottom: 0px;

  min-width: 400px;
  left: 0px;
  right: 10px; 

  z-index: 99;
  background: #fff;
  /* rgba(0, 0, 0, 0.1); */
  /* background: red; */
  display: flex;
  flex-direction: column;
  justify-content: center; /* 垂直方向居中对齐 */
  align-items: center; /* 水平方向居中对齐 */
}
.percentage-value {
  display: block;
  margin-top: 10px;
  font-size: 28px;
}
.percentage-label {
  display: block;
  margin-top: 10px;
  font-size: 12px;
}
.demo-progress .el-progress--line {
  margin-bottom: 15px;
  width: 350px;
}
.demo-progress .el-progress--circle {
  margin-right: 15px;
}

/**  end of progress bar. */


@media (max-width: 600px) {
  .popup {
    display: none;
  }
}

.popupemoji {
  position: absolute;
  bottom: 15%;
  left: 0px;

  /* position: fixed;
        top: 100px;
        bottom: 200px;
        left: 270px;
        right: 200px;  */
  /* width:300px;
        height:300px; */
  z-index: 0;
  /* background: rgba(0, 0, 0, 0.1); */
  display: flex;
  /* justify-content: center;
        align-items: center; */
  /* border: 1px solid blue; */
}

.popup-inner {
  /* background:  rgba(0, 0, 0, 0.1); */
  /* position: relative; */
  padding: 32px;
  /* border: 1px solid black; */
}
/* .test{
  display: flex;
  place-items: center;
  width: 800px;
  height: 500px;
  background: blue;
} */
.filetextarea{
  width:100%;
  height:50%;
}
img {
  max-width: 100%; /* 设置最大宽度 */
  height: auto; /* 设置高度自动调整以保持等比例缩放 */
}
</style>